package com.weifly.weistock.module.stockbill;

import com.weifly.weistock.bo.MergeRecordResult;
import com.weifly.weistock.bo.record.RecordPairBO;
import com.weifly.weistock.core.constant.StockBillBusinessNameEnum;
import com.weifly.weistock.core.util.DateUtils;
import com.weifly.weistock.core.util.RecordUtils;
import com.weifly.weistock.module.stockbill.bo.*;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 账单工具方法
 *
 * @author weifly
 * @since 2020/01/15
 */
public class StockBillConverter {

    /**
     * 是卖出操作，则返回true
     */
    public static boolean isCloseRecord(StockRecordBO record) {
        StockBillBusinessNameEnum businessName = record.getBusinessName();
        // 证券卖出
        if (StockBillBusinessNameEnum.NAME_2.equals(businessName)) {
            return true;
        }
        // 担保品划出
        if (StockBillBusinessNameEnum.NAME_4.equals(businessName)) {
            return true;
        }
        // 还款卖出
        if (StockBillBusinessNameEnum.NAME_6.equals(businessName)) {
            return true;
        }
        return false;
    }

    public static boolean isOpenRecord(StockRecordBO record) {
        StockBillBusinessNameEnum businessName = record.getBusinessName();
        // 证券买入
        if (StockBillBusinessNameEnum.NAME_1.equals(businessName)) {
            return true;
        }
        // 担保品划入
        if (StockBillBusinessNameEnum.NAME_3.equals(businessName)) {
            return true;
        }
        // 融资买入
        if (StockBillBusinessNameEnum.NAME_5.equals(businessName)) {
            return true;
        }
        // 红股入帐
        if (StockBillBusinessNameEnum.NAME_8.equals(businessName)) {
            return true;
        }
        // 基金申购
        if (StockBillBusinessNameEnum.NAME_10.equals(businessName)) {
            return true;
        }
        return false;
    }

    /**
     * 获得未配对成交量
     */
    public static int getNotPairNumber(StockRecordBO record) {
        int totalPairNumber = 0;
        if (record.getPairList() != null) {
            for (RecordPairBO pair : record.getPairList()) {
                totalPairNumber += pair.getNumber();
            }
        }
        return record.getTradeNumber() - totalPairNumber;
    }

    public static void addRecordToSummary(StockSummaryBO summaryBO, StockRecordBO recordBO, MergeRecordResult result) {
        // key规则：发生日期_成交时间_委托编号
        String key = recordBO.getDate() + "_" + recordBO.getTime() + "_" + recordBO.getEntrustCode();
        StockRecordBO targetBO = summaryBO.getRecordMap().get(key);
        if (targetBO == null) {
            summaryBO.getRecordList().add(recordBO);
            summaryBO.getRecordMap().put(key, recordBO);
            if (result != null) {
                result.setInsert(result.getInsert() + 1);
            }
        } else {
            targetBO.copyPropForm(recordBO);
            if (result != null) {
                result.setUpdate(result.getUpdate() + 1);
            }
        }
    }

    public static StockHoldSummaryBO convertToStockHoldSummaryBO(StockSummaryBO stockSummaryBO) {
        if (stockSummaryBO == null) {
            return null;
        }
        // 计算dayList
        StockHoldSummaryBO holdSummaryBO = new StockHoldSummaryBO();
        holdSummaryBO.setStockCode(stockSummaryBO.getStockCode());
        holdSummaryBO.setStockName(stockSummaryBO.getStockName());
        List<StockHoldDayBO> dayList = holdSummaryBO.getDayList();
        Map<String, StockHoldDayBO> dayMap = new HashMap<>();
        for (StockRecordBO recordBO : stockSummaryBO.getRecordList()) {
            if (StockBillBusinessNameEnum.NAME_1.equals(recordBO.getBusinessName())) {
                addHold(dayMap, dayList, recordBO);
            } else if (StockBillBusinessNameEnum.NAME_2.equals(recordBO.getBusinessName())) {
                subtractHold(dayMap, dayList, recordBO);
            } else if (StockBillBusinessNameEnum.NAME_7.equals(recordBO.getBusinessName())) {
                // 股息入帐，忽略
            } else {
                throw new RuntimeException("不支持的BusinessName: " + recordBO.getBusinessName());
            }
        }
        // 计算date, totalHoldNumber
        SimpleDateFormat sdf = new SimpleDateFormat(DateUtils.FORMATTER_DATE);
        long currTime = System.currentTimeMillis();
        int totalHoldNumber = 0;
        for (StockHoldDayBO dayBO : dayList) {
            totalHoldNumber += dayBO.getHoldNumber();
            long holdDays = (currTime - DateUtils.parseDate(sdf, dayBO.getDate()).getTime()) / (1000 * 60 * 60 * 24);
            dayBO.setHoldDays((int) holdDays);
            dayBO.setTotalNumber(totalHoldNumber);
        }
        holdSummaryBO.setHoldNumber(totalHoldNumber);

        return holdSummaryBO;
    }

    private static void addHold(Map<String, StockHoldDayBO> dayMap, List<StockHoldDayBO> dayList, StockRecordBO recordBO) {
        String date = recordBO.getDate();
        if (dayMap.containsKey(date)) {
            StockHoldDayBO dayBO = dayMap.get(date);
            dayBO.setHoldNumber(dayBO.getHoldNumber() + recordBO.getTradeNumber());
        } else {
            StockHoldDayBO dayBO = new StockHoldDayBO();
            dayBO.setDate(date);
            dayBO.setHoldNumber(recordBO.getTradeNumber());
            dayMap.put(date, dayBO);
            dayList.add(dayBO);
        }
    }

    private static void subtractHold(Map<String, StockHoldDayBO> dayMap, List<StockHoldDayBO> dayList, StockRecordBO recordBO) {
        int subtractNumber = recordBO.getTradeNumber();
        while (subtractNumber > 0) {
            if (dayList.isEmpty()) {
                throw new RuntimeException("持仓数量不够，无法核销卖出数量: " + subtractNumber);
            }
            StockHoldDayBO dayBO = dayList.get(0);
            if (dayBO.getHoldNumber() <= subtractNumber) {
                dayMap.remove(dayBO.getDate());
                dayList.remove(0);
                subtractNumber = subtractNumber - dayBO.getHoldNumber();
            } else {
                dayBO.setHoldNumber(dayBO.getHoldNumber() - subtractNumber);
                subtractNumber = 0;
            }
        }
    }

    public static GetStockRecordRequest convertToGetStockRecordRequest(HttpServletRequest request, int limit) {
        GetStockRecordRequest queryRequest = new GetStockRecordRequest();
        queryRequest.setStockCode(request.getParameter("stockCode")); // 股票代码
        queryRequest.setDate(request.getParameter("date")); // 发生日期
        queryRequest.setTime(request.getParameter("time")); // 成交时间
        queryRequest.setEntrust(request.getParameter("entrust")); // 委托编号
        queryRequest.setLimit(limit + 1);
        return queryRequest;
    }

    public static List<StockSummaryBO> sortStockList(List<StockSummaryBO> stockList) {
        stockList.sort((d1, d2) -> {
            String d1Date = "", d1Time = "", d2Date = "", d2Time = "";
            if (d1.getRecordList().size() > 0) {
                StockRecordBO lastRecord = d1.getRecordList().get(d1.getRecordList().size() - 1);
                d1Date = lastRecord.getDate();
                d1Time = lastRecord.getTime();
            }
            if (d2.getRecordList().size() > 0) {
                StockRecordBO lastRecord = d2.getRecordList().get(d2.getRecordList().size() - 1);
                d2Date = lastRecord.getDate();
                d2Time = lastRecord.getTime();
            }
            if (!d2Date.equals(d1Date)) {
                return d2Date.compareTo(d1Date);
            } else {
                return d2Time.compareTo(d1Time);
            }
        });
        return stockList;
    }

    public static Map<String, Object> convertStockSummary(StockSummaryBO stockSummary) {
        Map<String, Object> recordInfo = new HashMap<>();
        recordInfo.put("stockCode", stockSummary.getStockCode() == null ? "" : stockSummary.getStockCode());
        recordInfo.put("stockName", stockSummary.getStockName() == null ? "" : stockSummary.getStockName());
        recordInfo.put("recordSize", stockSummary.getRecordList().size()); // 交易次数
        recordInfo.put("diffAmount", stockSummary.getDiffAmount() == null ? "" : stockSummary.getDiffAmount()); // 差额
        recordInfo.put("feeService", stockSummary.getFeeService() == null ? "" : stockSummary.getFeeService()); // 手续费
        recordInfo.put("feeStamp", stockSummary.getFeeStamp() == null ? "" : stockSummary.getFeeStamp()); // 印花税
        recordInfo.put("afterNumber", stockSummary.getAfterNumber() == null ? "" : stockSummary.getAfterNumber()); // 剩余数量
        String lastOrderTime = "";
        if (stockSummary.getRecordList().size() > 0) {
            StockRecordBO lastRecord = stockSummary.getRecordList().get(stockSummary.getRecordList().size() - 1);
            lastOrderTime = lastRecord.getDate() + " " + lastRecord.getTime();
        }
        recordInfo.put("lastOrderTime", lastOrderTime); // 最后交易时间
        return recordInfo;
    }

    public static Map<String, Object> convertStockRecord(StockRecordBO stockRecord) {
        Map<String, Object> recordInfo = new HashMap<>();
        recordInfo.put("date", stockRecord.getDate());
        recordInfo.put("time", stockRecord.getTime());
        recordInfo.put("entrustCode", stockRecord.getEntrustCode());
        recordInfo.put("businessName", stockRecord.getBusinessName().getName());
        recordInfo.put("tradePrice", stockRecord.getTradePrice());
        recordInfo.put("tradeNumber", stockRecord.getTradeNumber());
        recordInfo.put("tradeAmount", stockRecord.getTradeAmount());
        recordInfo.put("feeService", stockRecord.getFeeService());
        recordInfo.put("feeStamp", stockRecord.getFeeStamp());
        recordInfo.put("clearAmount", stockRecord.getClearAmount());
        recordInfo.put("diffAmount", stockRecord.getDiffAmount());
        recordInfo.put("pair", RecordUtils.makePairAttr(stockRecord.getPairList(), stockRecord.getTradeNumber()));
        return recordInfo;
    }
}
